/*
 * Copyright (c) 2005, Haxe China community .
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY HAXE CHINA COMMUNITY "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL HAXE CHINA COMMUNITY BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 * 
 * Copyright (c) 1998 著作权由Haxe中国社区所有。著作权人保留一切权利。
 * 
 * 这份授权条款，在使用者符合以下三条件的情形下，授予使用者使用及再散播本
 * 软件包装原始码及二进位可执行形式的权利，无论此包装是否经改作皆然：
 * 
 * 对于本软件源代码的再散播，必须保留上述的版权宣告、此三条件表列，以
 * 及下述的免责声明。
 * 对于本套件二进位可执行形式的再散播，必须连带以文件以及／或者其他附
 * 于散播包装中的媒介方式，重制上述之版权宣告、此三条件表列，以及下述
 * 的免责声明。
 * 
 * 免责声明：本软件是由Haxe中国社区及本软件之贡献者以现状（"as is"）提供，
 * 本软件包装不负任何明示或默示之担保责任，包括但不限于就适售性以及特定目
 * 的的适用性为默示性担保。Haxe中国社区及本软件之贡献者，无论任何条件、
 * 无论成因或任何责任主义、无论此责任为因合约关系、无过失责任主义或因非违
 * 约之侵权（包括过失或其他原因等）而起，对于任何因使用本软件包装所产生的
 * 任何直接性、间接性、偶发性、特殊性、惩罚性或任何结果的损害（包括但不限
 * 于替代商品或劳务之购用、使用损失、资料损失、利益损失、业务中断等等），
 * 不负任何责任，即在该种使用已获事前告知可能会造成此类损害的情形下亦然。
 * 
 * 本许可证之中文译本中若有任何歧义，以英文版本为准。
 */
package com.haxecn.network;
import flash.utils.ByteArray;
import flash.utils.Endian;
import com.haxecn.network.cmd.CMDFormat;

/**
	The BinDataGen class.<br />
	Author Icebird<br />
	Detail: <br />
	Events: none.
**/


class BinDataProcessor
{
	/**
		Pack data to binary Squence<br />
		Parameters：<br />
		command Command format used to format the data.<br />
		data Datas to package<hr />
		return:	Data squence finished .<hr />
		Error：none
	**/
	public static function pack(command:CMDFormat, data:Hash<Dynamic>):ByteArray
	{
		var result:ByteArray = new ByteArray();
		result.endian = Endian.LITTLE_ENDIAN;
		result.writeUnsignedInt(command.cmdID);
		for(i in 0...command.format.length)
		{
			switch(command.format.charAt(i))
			{
				case '0':
					//Write a byte type data
					result.writeByte(data.get(command.variableNames[i]));
				case '1':
					//Write a short type data
					result.writeShort(data.get(command.variableNames[i]));
				case '2':
					//Write a int type data
					result.writeInt(data.get(command.variableNames[i]));
				case '3':
					//Write a untyped int type data
					result.writeUnsignedInt(data.get(command.variableNames[i]));
				case '4':
					//Write a byte sequence (with a length info first)
					result.writeUnsignedInt(data.get(command.variableNames[i]).length);
					result.writeBytes(data.get(command.variableNames[i]));
				case '5':
					//Write a string (with a length info first)
					var tempBytes:ByteArray = new ByteArray();
					tempBytes.writeUTFBytes(data.get(command.variableNames[i]));
					result.writeUnsignedInt(tempBytes.length);
					result.writeBytes(tempBytes);
				default:
			}
		}
		return result;
	}

	public static function unpack(command:CMDFormat, data:ByteArray):Hash<Dynamic>
	{
		var tempBytes:ByteArray;
		var dataLength:UInt;
		var result:Hash<Dynamic> = new Hash();
		data.endian = Endian.LITTLE_ENDIAN;
		data.position = 4;
		for(i in 0...command.format.length)
		{
			switch(command.format.charAt(i))
			{
				case '0':
					//Read byte
					result.set(command.variableNames[i], data.readUnsignedByte());
				case '1':
					//Read short
					result.set(command.variableNames[i], data.readUnsignedShort());
					
				case '2':
					//Read int
					result.set(command.variableNames[i], data.readInt());
				case '3':
					//Read untyped int
					result.set(command.variableNames[i], data.readUnsignedInt());
				case '4':
					//Read data squence
					dataLength = data.readUnsignedInt();
					tempBytes = new ByteArray();
					if(dataLength >0)
					{
						data.readBytes(tempBytes,0,dataLength);
						result.set(command.variableNames[i], tempBytes);
					}
					else
					{
						result.set(command.variableNames[i], new ByteArray());
					}
				case '5':
					//Read string
					dataLength = data.readUnsignedInt();
					if(dataLength >0)
					{
						result.set(command.variableNames[i], data.readUTFBytes(dataLength));
					}
					else
					{
						result.set(command.variableNames[i], "");
					}
				default:
			}
		}
		return result;
	}

	/*
		Get the command format ID .
	*/
	public static function getID(data:ByteArray):UInt
	{
		data.endian = Endian.LITTLE_ENDIAN;
		data.position = 0;
		return data.readUnsignedInt();
	}
}
